package com.desin.modle.multithread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

public class CuCompletionService {


    // 创建线程池
    ExecutorService executor =
            Executors.newFixedThreadPool(3);
    // 创建CompletionService
    CompletionService<Integer> cs = new
            ExecutorCompletionService<>(executor);

    // 创建CompletionService1
    CompletionService<Integer> cs1 = new ExecutorCompletionService<>(executor);

    // 用于保存Future对象
    List<Future<Integer>> futures = new ArrayList<>(3);

    public Integer bb() throws InterruptedException, ExecutionException {

//提交异步任务，并保存future到futures
        futures.add(
                cs.submit(() -> getPriceByS1()));
        futures.add(
                cs.submit(() -> getPriceByS2()));
        futures.add(
                cs.submit(() -> getPriceByS3()));
// 获取最快返回的任务执行结果
        Integer r = 0;
        try {
            // 只要有一个成功返回，则break
            for (int i = 0; i < 3; ++i) {
                r = cs.take().get();
                //简单地通过判空来检查是否成功返回
                if (r != null) {
                    break;
                }
            }
        } finally {
            //取消所有任务
            for (Future<Integer> f : futures) {
                f.cancel(true);
            }
        }
// 返回结果
        return r;
    }

    public void aa() throws InterruptedException, ExecutionException {
        // 异步向电商S1询价
        cs.submit(() -> getPriceByS1());
// 异步向电商S2询价
        cs.submit(() -> getPriceByS2());
// 异步向电商S3询价
        cs.submit(() -> getPriceByS3());
// 将询价结果异步保存到数据库
        for (int i = 0; i < 3; i++) {
            Integer r = cs.take().get();
            executor.execute(() -> save(r));
        }
    }

    private void save(Integer r) {
        System.out.println(r);
    }

    private Integer getPriceByS3() throws InterruptedException {
        Thread.sleep(3000);
        return 3;
    }

    private Integer getPriceByS2() throws InterruptedException {
        Thread.sleep(2000);
        return 2;
    }

    private Integer getPriceByS1() throws InterruptedException {
        Thread.sleep(4000);
        return 1;
    }

    void sleep(int t, TimeUnit u) {
        try {
            u.sleep(t);
        } catch (InterruptedException e) {
        }
    }
}
